using System.Collections.Generic;
using OracleInternal.Common;
using OracleInternal.Secure.Network;

namespace OracleInternal.Network
{
	internal class EncryptionService : AnoService
	{
		internal byte[] drivers = new byte[12]
		{
			0,
			17,
			6,
			16,
			12,
			15,
			10,
			11,
			8,
			2,
			1,
			3
		};

		private int m_resp;

		private int i;

		internal static string[] ENCRYPTION_ANO_ID = new string[12]
		{
			"",
			"RC4_40",
			"RC4_56",
			"RC4_128",
			"RC4_256",
			"DES40C",
			"DES56C",
			"3DES112",
			"3DES168",
			"AES128",
			"AES192",
			"AES256"
		};

		internal const int ENCRYPTION_NULL_ID = 0;

		internal const int ENCRYPTION_RC4_BAS_ID = 1;

		internal const int ENCRYPTION_RC4__56_ID = 8;

		internal const int ENCRYPTION_RC4_128_ID = 10;

		internal const int ENCRYPTION_RC4_256_ID = 6;

		internal const int ENCRYPTION_DES__40_ID = 3;

		internal const int ENCRYPTION_DES__56_ID = 2;

		internal const int ENCRYPTION_DES_112_ID = 11;

		internal const int ENCRYPTION_DES_168_ID = 12;

		internal const int ENCRYPTION_AES_128_ID = 15;

		internal const int ENCRYPTION_AES_192_ID = 16;

		internal const int ENCRYPTION_AES_256_ID = 17;

		private byte[] ENCRYPTION_ORACLE_ID = new byte[12]
		{
			0,
			1,
			8,
			10,
			6,
			3,
			2,
			11,
			12,
			15,
			16,
			17
		};

		private bool encryptionActivated;

		private static int NUM_ENCRYPTION_SUBPACKETS = 2;

		internal override int Initialize(SessionContext sessCtx)
		{
			ConnectionOption conops = sessCtx.m_conops;
			SqlNetOraConfig sNOConfig = conops.SNOConfig;
			string level = ((conops.Encryption != null) ? conops.Encryption : sNOConfig["sqlnet.encryption_client"]);
			string value = ((conops.EncryptionTypes != null) ? conops.EncryptionTypes : sNOConfig["sqlnet.encryption_types_client"]);
			base.Initialize(sessCtx);
			m_service = 2;
			m_level = AnoService.translateAnoValue(level);
			if (m_level == -1)
			{
				throw new NetworkException(-6304);
			}
			string[] userList = SqlNetOraConfig.MultipleValueSplit(value);
			userList = AnoService.ValidateUserChoiceDrivers(userList, ENCRYPTION_ANO_ID);
			if (userList == null)
			{
				return 0;
			}
			m_userChoiceDriversId = new List<int>(userList.Length);
			for (i = 0; i < userList.Length; i++)
			{
				m_userChoiceDriversId.Add(GetDriverID(ENCRYPTION_ANO_ID, userList[i]));
			}
			createDriversListWithLevel(ref m_userChoiceDriversId, m_level);
			m_selectedDrivers = new byte[m_userChoiceDriversId.Count];
			for (i = 0; i < m_selectedDrivers.Length; i++)
			{
				m_selectedDrivers[i] = ENCRYPTION_ORACLE_ID[m_userChoiceDriversId[i]];
			}
			int num = 1;
			if (m_userChoiceDriversId.Count == 0)
			{
				if (m_level == 3)
				{
					throw new NetworkException(-6304);
				}
				num |= 8;
			}
			else if (m_level == 3)
			{
				num |= 0x10;
			}
			return num;
		}

		internal EncryptionService()
		{
		}

		internal override void SendServiceData()
		{
			SendHeader(3);
			m_anoComm.SendVersion();
			m_anoComm.SendRaw(m_selectedDrivers);
			m_anoComm.SendUB1(1);
		}

		internal override int GetServiceDataLength()
		{
			return 17 + m_selectedDrivers.Length;
		}

		internal override void ReceiveServiceData(int numSubPackets)
		{
			m_version = m_anoComm.ReceiveVersion();
			m_resp = m_anoComm.ReceiveUB1();
			int num = m_selectedDrivers.Length;
			if (num <= 0)
			{
				return;
			}
			for (i = 0; i < num; i++)
			{
				if (m_selectedDrivers[i] == m_resp)
				{
					m_algID = m_resp;
					break;
				}
			}
		}

		internal override void ValidateResponse()
		{
		}

		internal override void ActivateAlgorithm()
		{
			Ano ano = m_sessCtx.m_ano;
			if (m_algID != 0)
			{
				switch (m_algID)
				{
				case 11:
					m_sessCtx.encryptionAlg = new DES112();
					break;
				case 12:
					m_sessCtx.encryptionAlg = new DES168();
					break;
				case 1:
					m_sessCtx.encryptionAlg = new RC4(A_0: true, 40);
					break;
				case 8:
					m_sessCtx.encryptionAlg = new RC4(A_0: true, 56);
					break;
				case 10:
					m_sessCtx.encryptionAlg = new RC4(A_0: true, 128);
					break;
				case 6:
					m_sessCtx.encryptionAlg = new RC4(A_0: true, 256);
					break;
				case 15:
					m_sessCtx.encryptionAlg = new AES(1, 1);
					break;
				case 16:
					m_sessCtx.encryptionAlg = new AES(1, 2);
					break;
				case 17:
					m_sessCtx.encryptionAlg = new AES(1, 3);
					break;
				}
				if (m_sessCtx.encryptionAlg == null)
				{
					throw new NetworkException(12649);
				}
				m_sessCtx.cryptoBlockSize = 16;
				m_sessCtx.encryptionAlg.init(ano.skey, ano.getInitializationVector());
				m_sessCtx.cryptoNeeded = true;
			}
		}
	}
}
